﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using Slam;
using Slam.Configuration;
using Microsoft.SharePoint;
using SlamCms.Common;
using SlamCms.Configuration;
using SlamCms.SharePoint.Publishing.Data;

namespace SlamCms.SharePoint.Publishing.Services
{
	public static class RedirectionService
	{
		public static void RedirectToDocument(string slamId)
		{
			RedirectToDocument(slamId, false);
		}

		public static void RedirectToDocument(string slamId, bool published)
		{
			using (var context = GetDataContext())
			{
				var location = context.ExecuteQuery<ContentItemLocation>(String.Format(Queries.RetrieveContentItemLocation, GetDataSchema(), slamId)).FirstOrDefault();
				if (location != null)
				{
					using (SPSite siteCollection = new SPSite(location.SiteCollectionID))
					{
						using (SPWeb site = siteCollection.AllWebs[location.SiteID])
						{
							SPList list = site.Lists[location.ListID];
							SPListItem listItem = list.Items.GetItemById(location.ListRelativeID);
							if (listItem.File != null)
							{
								string documentUrl = listItem.File.Url.TrimStart('/');
								if (list.EnableModeration && list.EnableVersioning && listItem.HasPublishedVersion && published && listItem.ModerationInformation.Status != SPModerationStatusType.Approved)
								{
									int liveVersionId = 0;
									for (int i = 0; i < listItem.Versions.Count; i++)
									{
										if (listItem.Versions[i].Level == SPFileLevel.Published)
										{
											liveVersionId = listItem.Versions[i].VersionId;
											break;
										}
									}
									documentUrl = "_vti_history/" + liveVersionId.ToString() + "/" + documentUrl;
								}
								string redirectUrl = String.Format("{0}/{1}/{2}", ConfigurationManager.Environment.DefaultApplication.AdminUrl.TrimEnd('/'), site.ServerRelativeUrl.TrimStart('/').TrimEnd('/'), documentUrl);
								HttpContext.Current.Response.Redirect(redirectUrl);
							}
							else
							{
								throw new Exception("Retrieve document failed.  SlamId does not match a docoument library item.");
							}
						}
					}
				}
				else
				{
					throw new Exception("Retrieve document failed.  SlamId does not match ContentItem.");
				}
			}
		}

		public static void RedirectToEditForm(string slamId)
		{
			RedirectToEditForm(slamId, ConfigurationManager.Environment.DefaultApplication.FrontEndUrl);
		}

		public static void RedirectToEditForm(string slamId, string returnUrl)
		{
			using (var context = GetDataContext())
			{
				var redirectUrl = context.ExecuteQuery<string>(String.Format(Queries.RetrieveEditFormUrlForContentItem, GetDataSchema(), slamId)).FirstOrDefault();
				if (!string.IsNullOrEmpty(redirectUrl))
				{
					redirectUrl = "{0}&Source={1}".F(redirectUrl, HttpContext.Current.Server.UrlEncode("/_layouts/SlamCMS/Redirector.aspx?to=frontEnd&ReturnUrl={0}".F(HttpContext.Current.Server.UrlEncode(returnUrl))));
					redirectUrl = Path.Combine(ConfigurationManager.Environment.DefaultApplication.AdminUrl, redirectUrl.TrimStart('/'));
					HttpContext.Current.Response.Redirect(redirectUrl);
				}
				else throw new Exception("Retrieve edit form url query failed.");
			}
		}

		//todo: these three methods below should be in a shared class as they're not specific to redirection and could probably be useful elsewhere
		public static DataContext GetDataContext()
		{
			var slamConfiguration = ComponentService.GetInstance<IConfigurationManager>();
			var connectionString = string.Empty;

			if (slamConfiguration is XmlConfigurationManager)
				connectionString = ((XmlSqlDataMapping)GetDataMapping()).GetConnectionString();

			var section = slamConfiguration.GetSection<ConnectionStringSection>("ConnectionStrings");
			connectionString = string.IsNullOrEmpty(connectionString) ? section.Default : section.GetConnectionString(connectionString);

			if (connectionString == string.Empty)
				throw new Exception("Connection string not found in slam.config");

			return new DataContext(connectionString);
		}

		public static DataMapping GetDataMapping()
		{
			var slamConfiguration = ComponentService.GetInstance<IConfigurationManager>();
			var currentDataMapping = slamConfiguration.DataMapping;
			var siteCollection = SPContext.GetContext(HttpContext.Current).Site.ServerRelativeUrl.TrimStart('/');

			if (!string.IsNullOrEmpty(siteCollection) && slamConfiguration.DataMappings.ContainsKey(siteCollection))
				currentDataMapping = slamConfiguration.DataMappings[siteCollection];

			return currentDataMapping;
		}

		public static string GetDataSchema()
		{
			return ComponentService.GetInstance<IConfigurationManager>() is XmlConfigurationManager ? ((XmlSqlDataMapping)GetDataMapping()).GetDataSchema() : string.Empty;
		}
	}
}
